"use strict"

module.exports = function(app, settings){
	var log4js 		= require('log4js')
    , _         = require("lodash")
		, debug     = require('debug')('qywx-auth')
		, util      = require('util')
    , urljoin   = require('url-join')
    , template  = require('es6-template-strings')
    , shortid   = require('shortid')
		, url 			= require('url')
		, webRequest = require('request')
    , QywxAccessTokenClient = require("./QywxAccessTokenClient");


	var logger 		= log4js.getLogger("qywx-auth");

  const QYWX_LOGINPAGE_REQUEST_URL = "https://qy.weixin.qq.com/cgi-bin/loginpage?corp_id=${corpId}"
                                    + "&redirect_uri=${redirectUri}&state=${state}&usertype=${userType}";

  const GET_LOGIN_INFO_URL =
    "https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info?access_token=${accessToken}";
  /**
   * Entrypoint to authorize, will redirect to qywx auth url
      @param client_id
      @param domain
      @param corpId
      @param user_type
   */
  app.route("/auth")
    .get(function(req, res, next){
      var queryParameters = {
        client_id: req.query.client_id,
        domain: req.query.domain
      };

      if(req.query.cb){
        _.assign(queryParameters, { cb: req.query.cb }); //Add callback url parameter if it exists
      }

      var corpId = req.query.corpId;
      /**
       * redirect_uri支持登录的类型，有member(成员登录)、admin(管理员登录)、all(成员或管理员皆可登录)，默认值为admin
       * 非必需字段
       */
      var userType = req.query.user_type || 'admin';


      var redirectUri = url.format({
          protocol: req.get('X-Forwarded-Proto') || req.protocol,
          host: req.get('host'),
          pathname: urljoin(req.baseUrl, "token"),
          query: queryParameters
      });

      var qywxAuthUrl = template(QYWX_LOGINPAGE_REQUEST_URL, {
        corpId: corpId,
        redirectUri: redirectUri,
        state: shortid.generate(),
        userType: userType
      });

      //return res.render("qywxLogin", { authUrl: qywxAuthUrl });

      return res.redirect(qywxAuthUrl);
    });

  app.route("/token")
    .get(function(req, res, next){
      debug("auth callback from qywx : ", req.originalUrl);
      var authCode 	= req.query.auth_code;
      var expiresIn = req.query.expires_in;
      var cb 				= req.query.cb;
      var clientId  = req.query.client_id;
      var domain    = req.query.domain; //Name of domain

      /**
      * We should cache domain in app locals context object
      */
      app.locals.context.get(domain, function(err, ctx){
        if(err) return res.status(500).json({
          success: false,
          errCode: 500,
          errMsg: err.message
        });

        var isValidClient = false;
        for( var i=0; i < ctx.clients.length; i++){
  				var client = ctx.clients[i];
  				debug("client in domain: ", client);
  				if(client == clientId)	{
  					isValidClient = true;
  					break;
  				}
  			}

        if(!isValidClient){
          return res.status(401).json({
            success: false,
            errCode: 401,
            errMsg: "invalid_client"
          });
        }

        //retriev new token
        var corpId 			= ctx.qywx.corpId;
        var corpSecret 	= ctx.qywx.corpSecret;

        if(!ctx.qywxClient){
          ctx.qywxClient = QywxAccessTokenClient({
            corpId: corpId,
            corpSecret: corpSecret
          });
        }
        /*
        * Got access token
        */
        ctx.qywxClient.get(function(err, data){
          if(err){
						logger.error(err);

            return res.status(500).json({
              success: false,
              errCode: 500,
              errMsg: err.message
            });
          }

          //Retrieve user info
  				var getLoginInfoUrl = template(GET_LOGIN_INFO_URL, { accessToken: data.accessToken});

          webRequest.post({
  					url: getLoginInfoUrl
  					,headers: {'Content-Type': 'application/json'}
  					,body: JSON.stringify({
  	              "auth_code": authCode
  	        })
  				}, function(error, response, body){
  						if(error){
  							logger.error(error);
  							return res.status(500).json({
  								success: false,
  								errCode: 500,
  								errMsg: 'failed_to_retrieve_login_info',
  								internalError: err
  							});
  						}

  						debug("get login info: ", body);

  						try{
  							var data = JSON.parse(body);

  							if(data.errcode){
  								return res.status(500).json({
  									success: false,
  									errCode: data.errcode,
  									errMsg: data.errmsg
  								});
  							}

  							//Generate JWT token
  							var claims = {
  							  sub: (data.usertype == 1 || data.usertype == 3) ? data.user_info.email : data.user_info.userid,
  							  iss: req.get('host'),
  								detail: data
  							};

  	        		var accessToken = jwt.sign(claims, domain.jwt.secret
  														, {
  																algorithms: ['RS256', 'HS256']
  																,expiresIn: domain.jwt.expiresIn
  												 		}
  	        						);
  							if(cb){
  								var callback = url.parse(cb);

  								var query = _.assign({ access_token: accessToken }, callback.query );

  								var gotoUrl = url.format({
  									protocol: callback.protocol
  									,host: callback.host
  									,query : query
  								});

  								return res.redirect(gotoUrl);

  							}
  						}catch(error){
  							return res.status(500).json({
  								success: false,
  								errCode: 500,
  								errMsg: error.message,
  								internalError: error
  							});
  						}
  				});
        });
      });
    });
}
